using System;
using System.Linq;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Collections.Generic;


namespace Cassandraemon.FullText
{

	public class NGramnAnalyzer : IAnalyzer
	{
		public int NGramMinSize { get; set; }
		
		public int NGramMaxSize { get; set; }
		
		public NGramnAnalyzer ()
		{
			NGramMaxSize = 2;
			NGramMinSize = 1;
		}
		
		public NGramnAnalyzer (int ngramMaxSize, int ngramMinSize)
		{
			if(ngramMinSize > ngramMaxSize) 
				throw new ArgumentException("You should set ngramMaxSize bigger than ngramMinSize.");
				
			NGramMaxSize = ngramMaxSize;
			NGramMinSize = ngramMinSize;
		}

		public Dictionary<string, List<int>> MakeRegsitData (string text)
		{
			var result = new Dictionary<string, List<int>>();
			var queue = new Queue<string>();

			var t = text.ToLower().Normalize();
			
			var elements = StringInfo.GetTextElementEnumerator(t);
			
			while(elements.MoveNext())
			{
				queue.Enqueue(elements.GetTextElement());
				if(queue.Count > NGramMaxSize) queue.Dequeue();
				
				GetTerm(result, queue.ToArray(), elements.ElementIndex);
			}
			
			return result;
		}
		
		
		private void GetTerm(Dictionary<string, List<int>> dic, string[] array, int index)
		{
			int count = Math.Min(NGramMaxSize, array.Length);
			
			for(int i=NGramMinSize-1 ; i<count; i++)
			{
				var s = string.Join(string.Empty, array, array.Length - i - 1, i + 1);
				
				if(!dic.ContainsKey(s)) dic.Add(s, new List<int>());
				
				dic[s].Add(index - i);
			}
		}
		
		
		public List<string> SplitQueryPhrase (string phrase)
		{
			var t = phrase.ToLower().Normalize();
			
			var info = new StringInfo(t);
			if(info.LengthInTextElements < NGramMinSize) return new List<string>();
			if(info.LengthInTextElements <= NGramMaxSize) return new List<string>{phrase};
			
			var result = new List<string>();
			var queue = new Queue<string>();
			
			var elements = StringInfo.GetTextElementEnumerator(t);
			
			while(elements.MoveNext())
			{
				queue.Enqueue(elements.GetTextElement());
				
				if(queue.Count == NGramMaxSize)
				{
					var s = string.Join(string.Empty, queue.ToArray());
					result.Add(s);
					queue.Dequeue();
				}
			}
			
			return result;
		}
		
	}
}
